package com.koron.css2;

import com.koron.common.stub.Port;
import com.koron.css2.serviceManage.bean.*;
import com.koron.css2.serviceManage.service.ServerService;
import com.koron.css2.serviceManage.utils.CommonUtils;
import com.koron.css2.serviceManage.utils.JsonUtils;
import com.koron.css2.serviceManage.utils.PageDetailLog;
import com.koron.util.Constant;
import com.koron.util.DBSourceUtils;
import com.koron.util.InitParam;
import com.koron.util.Tools;
import nl.bitwalker.useragentutils.UserAgent;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.koron.ebs.mybatis.ADOConnection;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.swan.bean.MessageBean;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 附件上传
 * @author bin
 *
 */
@Controller
public class AccessoryUploadAction {
	

	
	@Autowired
	private ServerService serverService; // 服务管理类

	private static Logger logger = LogManager.getLogger(InterFaceAction.class);

	// 用于存储查询过的服务配置信息，这里不放redis而是放本地内存，访问更快
	private HashMap<String, TService> tServiceMap = new HashMap<>();
	
	// 用于存储所有接口的实例，在接口被调用一次之后，实例对象存储在这里，方便后续调用
	private HashMap<String, AccessoryInterface> serverMap = new HashMap<String, AccessoryInterface>();

	/**
	 * 根据不同的数据连接，通过业务实体对象，执行具体的服务信息
	 * 
	 * @param factory         数据库连接
	 * @param serverInterface 业务实体对象
	 * @param userInfo        用户信息
	 * @param requestBean     请求数据
	 * @return
	 */
	@TaskAnnotation("execInterface")
	public static MessageBean<?> execInterface(SessionFactory factory, AccessoryInterface acessoryInterface,
			UserInfoBean userInfo, RequestBean requestBean, List<MultipartFile> files) throws Exception {
		MessageBean<?> ret =  acessoryInterface.upload(factory, userInfo, requestBean, files);
		if(ret.getCode() != Constant.MESSAGE_INT_SUCCESS) {
			factory.close(false);
		}
		return ret;
	}

	/**
	 * 所有业务系统操作数据的统一入口
	 * 
	 * @param json 请求的对象数据
	 * @param request     请求Servlet对象
	 * @return ResponseBean 返回结果
	 * @throws Exception 
	 */
	@ResponseBody
	@RequestMapping(value = ("/accessoryUpload.api"), method = RequestMethod.POST)
	public ResponseBean service(@RequestParam(required = true, name = "file") List<MultipartFile> files,
		     @RequestParam(required = true, name = "json") String json, HttpServletRequest request) throws Exception {
		ResponseBean responseBean = new ResponseBean();
		RequestBean requestBean = JsonUtils.jsonToPojo(json, RequestBean.class);
		// 对busiCode,sysType判空
		if (requestBean == null || StringUtils.isBlank(requestBean.getBusicode())
				|| StringUtils.isBlank(requestBean.getSysType())) {
			responseBean.setCode(Constant.ILLEGAL_PARAMETER);
			responseBean.setDescription("请求的json格式不正确,或者参数为空");
			return responseBean;
		}
		// 获取用户信息(包括用户信息，用户可选水司信息，用户当前水司信息)
		UserInfoBean userInfo = Tools.getLoginBean(requestBean.getToken());
		if (userInfo == null) {
			responseBean.setCode(Constant.MESSAGE_INT_NOLOGIN);
			responseBean.setDescription("当前登录信息失效，请重新登录后再操作。");
			return responseBean;
		}

		// 获取服务信息
		TService tService = getInterfaceInfo(requestBean.getBusicode(), requestBean.getToken());
		if (tService == null) {
			responseBean.setCode(Constant.NO_DATA);
			responseBean.setDescription(requestBean.getBusicode() + "服务不存在");
			return responseBean;
		}
		// 判断服务是否停用
		if (tService.getStatus() == 0) {
			responseBean.setCode(Constant.SERVER_DISABLE);
			responseBean.setDescription(requestBean.getBusicode() + "该服务已停用");
			return responseBean;
		}
		// 检查用户是否有该服务的权限
		if (!checkRight(userInfo, tService, request.getHeader("url"), requestBean)) {
			responseBean.setCode(Constant.NO_AUTHORITY);
			responseBean.setDescription("您无当前操作的权限("+requestBean.getBusicode()+")，请联系管理员处理！");
			return responseBean;
		}
		// 执行服务
		try {
			//数据库连接别名
			String dbEnv = "_default";
			/*
			 * 001表示运维平台，002营收系统，003服务分析系统
			 */
		    if(userInfo.getCurService().equals("002")) {
				dbEnv = DBSourceUtils.getDbEnv(userInfo.getCurWaterCode());
			}else if(userInfo.getCurService().equals("003")) {
				//TODO
			}
			if(dbEnv == null){
				throw new RuntimeException("水司编号为："+userInfo.getCurWaterCode()+"的数据源注册失败！");
			}
			
			// 从缓存中获取服务实例
			AccessoryInterface serverInterface = serverMap.get(requestBean.getBusicode());
			// 判断缓存中是否存在，不存在则实例化一个新的并放入缓存
			if (serverInterface == null) {
				serverInterface = (AccessoryInterface) Class.forName(tService.getClassName()).newInstance();
				serverMap.put(requestBean.getBusicode(), serverInterface);
			}
			
			// 调用ADO执行数据库操作
			MessageBean<?> runTask = ADOConnection.runTask(dbEnv, AccessoryUploadAction.class, "execInterface", serverInterface, userInfo, requestBean, files);
			responseBean.setCode(runTask.getCode());
			responseBean.setDescription(runTask.getDescription());
			responseBean.setData(runTask.getData());
		} catch (Exception e) {
			logger.error("操作失败", e);
			responseBean.setCode(Constant.MESSAGE_INT_FAIL);
			responseBean.setDescription(e.getMessage());
		}
		// 记录调用信息
		RecordLog(request, responseBean, requestBean, userInfo);
		return responseBean;
	}

	/**
	 * 从本地内存读取服务配置，如果没有就从数据库读取
	 * 
	 * @param busicode
	 * @param resource
	 * @param redisAavailable
	 * @return
	 */
	private TService getInterfaceInfo(String busicode, String token) {
		TService tService = tServiceMap.get(busicode);
		if (tService == null) {
			tService = ADOConnection.runTask("_default", serverService, "selectByServiceCode", TService.class,
					busicode);
			if(!InitParam.isDev) {
				tServiceMap.put(busicode, tService);
			}
		}
		return tService;
	}
	
	/**
	 * 检查用户权限
	 * 
	 * @param userInfo
	 * @param tService
	 * @param url
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private boolean checkRight(UserInfoBean userInfo, TService tService, String url, RequestBean requestBean) {
		if (userInfo.getUserInfo().getAcount().equals("admin")) {
			return true;
		}
		List<TServiceDetail> detailList =  tService.gettServiceDetails();
		if(detailList==null||detailList.size()==0) {//接口没有权限控制
			return true;
		}
		if("krrjdev123".equals(requestBean.getToken())){
			return true;
		}
		for(TServiceDetail detail :detailList) {
			//只有子系统，没有模块的，且子系统与当前用户登陆一致
			if(userInfo.getCurService().equals(detail.getSystemCode())&& StringUtils.isBlank(detail.getModuleId())) {
				return true;
			}else if(userInfo.getCurService().equals(detail.getSystemCode())&& StringUtils.isNotBlank(detail.getModuleId())&&
					detail.getModuleId().substring(detail.getModuleId().indexOf("_")+1).equals(url)) {
				//模块不为空,且模块编号与url地址一致，要调用接口验证权限
				Port port = null;
				if("001".equals(userInfo.getCurService())) {
					port = new Port(ApplicationConfig.appMaintainAppid, ApplicationConfig.appMaintainSecret);
				}else if("002".equals(userInfo.getCurService())) {
					port = new Port(ApplicationConfig.appCustomerAppid, ApplicationConfig.appCustomerSecret);
				}else if("003".equals(userInfo.getCurService())) {
					port = new Port(ApplicationConfig.appAnalysisAppid, ApplicationConfig.appAnalysisSecret);
				}
				try {
					MessageBean<?> test =port.operateTest(detail.getModuleId(),userInfo.getUserInfo().getCode() ,"{}");
					if(test ==null || test.getCode() != Constant.MESSAGE_INT_SUCCESS) {
						return false;
					}else {
						Map<String,Boolean> m = (Map<String,Boolean>)test.getData();
						if(!m.get(detail.getModuleId())) { //返回没有操作权限
							return false;
						}else {
							return true;
						}
					}
				} catch (Exception e) {
					return false;
				}
			}
		}
		//TODO 重写上面权限认证方法
		return true; //false
	}

	/**
	 * 记录调用日志
	 * 
	 * @param request
	 * @param responseBean
	 * @param requestBean
	 * @param userInfo
	 */
	private void RecordLog(HttpServletRequest request, ResponseBean responseBean, RequestBean requestBean,
			UserInfoBean userInfo) {
		try {
			RecordBean recordBean = new RecordBean();
			String ua = request.getHeader("User-Agent");
			UserAgent userAgent = UserAgent.parseUserAgentString(ua);
			String browser = userAgent.getBrowser().getName();
			recordBean.setBrowserType(browser);
			recordBean.setWaterGroup(userInfo.getCurWaterCode());
			if (StringUtils.isBlank(userInfo.getCurWaterCode())) {
				recordBean.setWaterGroup("运维平台");
			}
			recordBean.setComments("调用" + requestBean.getBusicode());
			recordBean.setIpAddr(CommonUtils.getIpAddress(request));
			if (!StringUtils.isBlank(request.getHeader("url"))) {
				recordBean.setPageAddr(request.getHeader("url"));
			} else {
				recordBean.setPageAddr("abc(请求头header中未传递url信息)");
			}
			recordBean.setCaller(userInfo.getUserInfo().getAcount());
			recordBean.setCreateName(userInfo.getUserInfo().getName());
			recordBean.setCreateTime(CommonUtils.getCurrentTime());
			recordBean.setServiceCode(requestBean.getBusicode());
			recordBean.setRequest(JsonUtils.objectToJson(requestBean));
			recordBean.setResponse(JsonUtils.objectToJson(responseBean));

			PageDetailLog.put(recordBean);
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
	}

    @RequestMapping(value = "/relay.htm")
    public void relay(@RequestParam("fileServicePath") String url, @RequestParam("fileName") String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException, Exception{
		//转发客户端
		HttpURLConnection httpConnection=null;
		httpConnection = (HttpURLConnection) new URL(url).openConnection();
		httpConnection.setRequestMethod("POST");
		httpConnection.setDoOutput(true);
		httpConnection.setDoInput(true);
		httpConnection.setAllowUserInteraction(true);
		httpConnection.setReadTimeout(2 * 60 * 1000);
		httpConnection.setConnectTimeout(2 * 60 * 1000);
		httpConnection.connect();
		httpConnection.getOutputStream().flush();
		//返回结果
		response.setContentType(httpConnection.getContentType());
		response.setHeader("Access-Control-Allow-Origin", "*");
		if ("application/force-download".equals(httpConnection.getContentType())) {
			response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
		}
		response.setCharacterEncoding(httpConnection.getContentEncoding());
//		response.setContentLengthLong(httpConnection.getContentLengthLong());
    	response.getOutputStream().write(getDatas(httpConnection.getInputStream()));
    }
    
	public static byte[] getDatas(InputStream in) throws Exception
	{
		byte[] datas = new byte[24576];
		int len = 0;
		int count = 0;
		List<byte[]> ls = new ArrayList<byte[]>();
		byte[] temp;   
		while((len=in.read(datas))!=-1)
		{ 
			count += len;
			temp = new byte[len];
			for(int i=0;i<len;i++)
			{
				temp[i] = datas[i];
			}
			ls.add(temp);
		}  
		datas = new byte[count];
		count = 0;
		for(int i=0;i<ls.size();i++)
		{
			for(int j=0;j<ls.get(i).length;j++)
			{
				datas[count++]=ls.get(i)[j];
			}
		}
		return datas;
	}
}
